package Calculator.Parser.Elements;

import Calculator.Exceptions.DivisionByZeroException;
import Calculator.Exceptions.WrongExpressionException;
import Calculator.Parser.InfixParser;
import Calculator.Parser.Utilities;

public class Operator extends Token{

	public Operator(String id) {
		this.setId(id);
		if (Utilities.DIV.equals(id)){
			this.setPrecedence(Utilities.DIV_PRECEDENCE);
		} else if (Utilities.MUL.equals(id)){
			this.setPrecedence(Utilities.MUL_PRECEDENCE);
		} else if (Utilities.SUM.equals(id)){
			this.setPrecedence(Utilities.SUM_PRECEDENCE);
		} else {
			this.setPrecedence(Utilities.RES_PRECEDENCE);
		}
	}

	@Override
	public void performIteration(InfixParser infixParser) {
		if (!infixParser.getOperatorStack().isEmpty()){
			Boolean moreChanges = Boolean.TRUE;
			while (!infixParser.getOperatorStack().isEmpty() && moreChanges){
				Token operator = infixParser.getOperatorStack().peek();
				if (!Utilities.LEFT_PARENTHESIS.equals(operator.getId()) 
						&& operator.getPrecedence() != null 
						&& this.getPrecedence() <= operator.getPrecedence()){
					infixParser.getOperatorStack().pop();
					infixParser.getOutput().add(operator);
				} else {
					moreChanges = Boolean.FALSE;
				}
			}
		}
		infixParser.getOperatorStack().push(this);
	}
	
	public Double operate(Double x1, Double x2) throws DivisionByZeroException{
		if (Utilities.DIV.equals(getId())){
			if (x2 == 0){
				throw new DivisionByZeroException();
			}
			return x1 / x2;
		} else if (Utilities.MUL.equals(getId())){
			return x1 * x2;
		} else if (Utilities.SUM.equals(getId())){
			return x1 + x2;
		} else {
			return x1 - x2;
		}
	}

	@Override
	public void checkCorrectSyntax(Token t) throws WrongExpressionException {
		if (!t.isNumber() && !Utilities.LEFT_PARENTHESIS.equals(t.getId())){
			throw new WrongExpressionException(this, t);
		}
	}

	@Override
	public Boolean isOperator() {
		return Boolean.TRUE;
	}

	@Override
	public Boolean isNumber() {
		return Boolean.FALSE;
	}

}
